import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { useForm } from '@formily/react';
import { Button, message, Modal, Tabs } from 'antd';
import '../../style.less';
import cls from 'classnames';
import { ColumnType } from 'rc-table/lib/interface';
import {
  ActionEnum,
  actionHeader,
  Actions,
  arrIsEmpty,
  InputTypeEnum,
  getPropHeader,
  TabsConfig,
} from '../../shared';
import { isFunction } from 'lodash';
import FieldForm from './FieldForm';
import { ActionConfigType, RecordType } from '../../interfaces';
import { useQueryFields } from '@inbiz/hooks';
import EditableTable, { IColumns } from '@inbiz/basic/EditableTable';
import { getPageTree, tileTree } from '@inbiz/setters';
import { getPlatform, uuid } from '@inbiz/utils';
import { Field } from '@formily/core';
import { getMessage, TextWidget } from '@inbiz/react';
import AuthForm, { useAuth } from '@inbiz/basic/AuthForm';

export interface ConfigColumn extends ColumnType<RecordType> {
  field?: string;
  alias?: string;
  visible?: boolean;
  searchable?: boolean;
  inputType?: InputTypeEnum;
}

interface ColumnConfigProps {
  onChange: (value: any) => void;
  prefixCls?: string;
  value: { [key: string]: any };
}

type EditableType = {
  editData?: any;
  dataIndex: string;
  render?: (value: string) => string;
};

const ColumnConfig: React.FC<ColumnConfigProps> = (props) => {
  const { prefixCls = 'inbiz-config-modal', value } = props;
  const [visible, setVisible] = useState(false);
  const [activeKey, setActiveKey] = useState('actions');
  const form = useForm();
  const formItemsRef = useRef({ formItems: value?.formItems });
  const [choosedAuth, changeHandle, generateFlag] = useAuth();
  const isInline = (form.query(/inlineEdit$/)?.take() as Field)?.value;
  const authOption = useMemo(() => {
    return (choosedAuth?.allInfo?.Children || []).map((ele) => ({
      value: ele.ObjectValue,
      label: ele.ObjectValue + `(${getMessage(ele.ObjectName)})`,
    }));
  }, [choosedAuth]);

  const refObj = useMemo(() => {
    return Object.keys(TabsConfig(isInline)).reduce((refObjs, key) => {
      refObjs[key] = React.createRef<EditableTable>();
      return refObjs;
    }, {});
  }, [value.tableValues]);

  const modelKey = visible
    ? (form.fields?.['form.senior.soure.x-component-props.sourceModel'] as unknown as Field)?.value
    : undefined;
  const [fields, loading] = useQueryFields(
    {
      key: modelKey,
      appId: form['appInfo']!.appId,
    },
    [modelKey],
  );

  const validateActionUnique = (actions: ActionConfigType[]) => {
    actions.reduce((groups: any, cur: ActionConfigType) => {
      if (groups[cur.actionType]) {
        const typeName = Actions().find((action) => action.value === cur.actionType)?.label;
        throw new Error(`操作类型${typeName || cur.actionName}重复`);
      }
      if (cur.actionType === ActionEnum.custom) {
        return groups;
      }
      groups[cur.actionType] = cur;
      return groups;
    }, {});
  };

  const newFields = useMemo(() => {
    return fields.filter((field) => !field.IsMany);
  }, [fields]);
  const [pages, setPages] = useState();
  const formatActions = useCallback(() => {
    if (loading) {
      return;
    }
    const newHeader = actionHeader(authOption, isInline, newFields).filter((col) => col.dataIndex !== 'auth');
    for (const col of newHeader) {
      if ((col as EditableType).dataIndex === 'page') {
        (col as EditableType).editData.options = pages;
      }
    }
    return newHeader;
  }, [pages, authOption]);
  const formatAttrs = useCallback(() => {
    if (loading || arrIsEmpty(newFields)) {
      return;
    }
    const PropHeader = getPropHeader();
    const newHeader = [...PropHeader];
    const sourceType = (form.query(/sourcetype$/)?.take() as Field)?.value;

    const newGroups = newFields.reduce((groups: any, field) => {
      const [modelName, attrName] = field.origin_FieldName?.split('$') || [];
      if (!field.Master) {
        field.label = attrName;
      }
      if (groups[field.ModelKey]) {
        groups[field.ModelKey].options.push(field);
      } else {
        groups[field.ModelKey] = {
          ...field,
          label: modelName,
          key: field.ModelKey,
          options: [field],
        };
      }
      return groups;
    }, {});
    for (const col of newHeader) {
      if ((col as EditableType).dataIndex === 'propName') {
        if (sourceType === 'api') {
          (col as EditableType).editData.options = newFields;
        }
        (col as EditableType).editData.optgroups = Object.keys(newGroups).map(
          (key) => newGroups[key],
        );
        (col as EditableType).render = (val: string) => {
          return val?.includes('$') ? val.replace('$', '.') : val;
        };
        (col as EditableType).editData.afterEdit = (index, record) => {
          const columnName = newFields?.find(ele => ele.value == record.propName)!.columnName
          return {
            ...record,
            columnName
          }
        }
        break;
      }
    }
    return newHeader;
  }, [newFields, loading]);
  const processor = {
    actions: formatActions,
    attrs: formatAttrs,
  };
  const addHandler = {
    attrs: () => {
      return { id: uuid(5, 5), width: 100, visible: '1' };
    },
  };

  const setData = useCallback(async () => {
    const promises = [];
    let flagList = [];
    for (const key of Object.keys(refObj)) {
      if (!refObj[key].current) {
        //没有点开其他tab
        promises.push(
          new Promise((resolve) => {
            resolve({ [key]: value?.tableValues?.[key] });
          }),
        );
        continue;
      }
      promises.push(
        new Promise((resolve, reject) => {
          refObj[key].current
            .getData()
            .then((res: any) => {
              if (key === 'actions') {
                res = res.map((ele) => ({ ...ele, show: true }));
                flagList = res.map((ele) => ({ value: ele.operationflag, label: ele.actionName }));
              }
              resolve({ [key]: res });
            })
            .catch((err: any) => {
              setActiveKey(key);
              reject(err);
            });
        }),
      );
    }

    Promise.all(promises)
      .then((values) => {
        let tableValues: { actions?: ActionConfigType[] } = {};
        for (const data of values) {
          tableValues = {
            ...tableValues,
            ...(data as any),
          };
        }
        if (tableValues.actions) {
          try {
            validateActionUnique(tableValues.actions);
          } catch (e: any) {
            message.error(e.message);
            return;
          }
        }
        setVisible(false);
        generateFlag(flagList).then(() => {
          props.onChange({
            tableValues,
            queryFields: newFields?.map((field) => {
              const [modelName] = field.origin_FieldName?.split('$') || [];
              return {
                ...field,
                label: !field.Master ? `${modelName}.${field.label}` : field.label,
              };
            }),
            formItems: {
              ...value?.formItems,
              ...formItemsRef.current.formItems,
            },
            auth: choosedAuth?.value,
          });
        });
      })
      .catch((err) => {
        console.log('config-err>>>', err);
      });
  }, [newFields, value, choosedAuth]);

  const handleAdd = useCallback(() => {
    return { id: uuid(5, 5) };
  }, []);

  useEffect(() => {
    if (!form['appInfo']) {
      return;
    }
    getPageTree(form['appInfo']).then((res) => {
      if (res) {
        setPages(
          tileTree(res).map((item: any) => {
            return {
              value: `${item.Route},${item.OutId}`,
              label: item.DisplayName,
            };
          }),
        );
      }
    });
  }, [form['appInfo']]);
  /**
   * 新建子表格时，
   * 给子表格属性-配置-属性添加默认值
   */
  const initTableAttrs = () => {
    if (fields && fields.length > 0 && !value.tableValues.attrs) {
      const newAttrs = fields.map((field) => ({
        propName: field.value,
        visible: '1',
        width: 100,
        id: uuid(5, 5),
      }));
      value.tableValues.attrs = newAttrs;
    }
  };

  useEffect(() => {
    initTableAttrs();
  }, [fields]);

  return (
    <>
      <Button
        type="primary"
        onClick={() => {
          if (
            !(form.fields['form.senior.soure.x-component-props.sourceModel'] as unknown as Field)
              ?.value
          ) {
            message.warn('请先选择查询数据源');
            return;
          }
          setVisible(true);
        }}
      >
        <TextWidget>SubTable.button.config</TextWidget>
      </Button>
      <Modal
        wrapClassName={`${cls(prefixCls)}`}
        width={getPlatform() == 'wap' ? '760px' : '60%'}
        visible={visible}
        title={<TextWidget>SubTable.button.config</TextWidget>}
        okText={<TextWidget>global.sure</TextWidget>}
        cancelText={<TextWidget>global.cancel</TextWidget>}
        onOk={setData}
        onCancel={() => setVisible(false)}
        destroyOnClose
      >
        <Tabs activeKey={activeKey} onChange={(key) => setActiveKey(key)}>
          {Object.keys(TabsConfig(isInline)).map((key) => {
            let config = TabsConfig(isInline, newFields)[key]['table'];
            const header = processor[key]?.() || config.header;
            const add = addHandler[key] || handleAdd;
            return (
              <Tabs.TabPane tab={config.name} key={key}>
                <FieldForm
                  initialValues={{
                    ...(value?.formItems || {}),
                    auth: value?.auth,
                  }}
                  formItemsRef={formItemsRef}
                  fields={config.formItems}
                  layout={config.layout}
                  otherFormItem={
                    key === 'actions' && (
                      <AuthForm
                        initialValues={props.value?.auth}
                        onChange={changeHandle}
                        withoutForm={true}
                      />
                    )
                  }
                />

                <EditableTable
                  className={'editable-table'}
                  rowKey={'id'}
                  columns={isFunction(header) ? header(authOption) : (header as IColumns)}
                  dataSource={value?.tableValues?.[key]}
                  rowSelection={{ columnWidth: 44 }}
                  isRowSelection={true}
                  addBtn={!config.hideButton}
                  deleteBtn={!config.hideButton}
                  disableDraggable={config.hideButton}
                  onAdd={add}
                  ref={refObj[key]}
                  scroll={{ y: 300 }}
                />
              </Tabs.TabPane>
            );
          })}
        </Tabs>
      </Modal>
    </>
  );
};

export default React.memo(ColumnConfig);
